/***************************************************
> Copyright (C) 2025 ==ASD== All rights reserved.
> File Name: hw7.c
> Author: asd
> Mail:3319941451@qq.com 
> Created Time: 2025年01月03日 星期五 20时51分26秒
***************************************************/
//服务器端客户端管理接口
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/epoll.h>
#include <signal.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>

// 定义结构体存储客户端信息（与其他客户端相关结构体类似，可根据实际情况调整）
typedef struct ClientInfo {
    int client_socket;
    struct sockaddr_in client_addr;
    char client_id[20];
} ClientInfo;

// 全局变量，用于存储客户端信息数组
ClientInfo clients[100];
int client_count = 0;

// 共享内存相关变量（用于与其他模块共享数据，这里简单示例）
void *shared_memory;
int shared_memory_fd;

// 信号量相关变量（用于同步对共享内存的访问，这里简单示例）
int sem_id;

// 函数声明
void handle_client_connection(int server_socket);
void receive_client_data(int client_socket);
void send_command_to_client(int client_socket, const char *command);

int main() {
    // 创建TCP套接字用于与客户端通信
    int server_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (server_socket == -1) {
        perror("Socket creation failed");
        return 1;
    }

    // 设置服务器地址结构体
    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(8890);
    server_addr.sin_addr.s_addr = INADDR_ANY;

    // 绑定套接字到地址和端口
    if (bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
        perror("Bind failed");
        return 1;
    }

    // 监听套接字
    if (listen(server_socket, 5) == -1) {
        perror("Listen failed");
        return 1;
    }

    // 创建epoll实例
    int epoll_fd = epoll_create1(0);
    if (epoll_fd == -1) {
        perror("Epoll create failed");
        return 1;
    }

    // 将服务器套接字添加到epoll监听事件中
    struct epoll_event event;
    event.events = EPOLLIN;
    event.data.fd = server_socket;
    if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_socket, &event) == -1) {
        perror("Epoll ctl add server socket failed");
        return 1;
    }

    // 创建共享内存（这里简单示例，实际可能需要根据具体需求调整）
    shared_memory_fd = shmget(IPC_PRIVATE, sizeof(char) * 1024, IPC_CREAT | 0666);
    if (shared_memory_fd == -1) {
        perror("shmget failed");
        return 1;
    }

    shared_memory = mmap(NULL, sizeof(char) * 1024, PROT_READ | PROT_WRITE, MAP_SHARED, shared_memory_fd, 0);
    if (shared_memory == MAP_FAILED) {
        perror("mmap failed");
        return 1;
    }

    // 创建信号量（这里简单示例，用于同步对共享内存的访问）
    sem_id = semget(IPC_PRIVATE, 1, IPC_CREAT | 0666);
    if (sem_id == -1) {
        perror("semget failed");
        return 1;
    }

    // 初始化信号量值为1
    union semun {
        int val;
    } sem_args;
    sem_args.val = 1;
    if (semctl(sem_id, 0, SETVAL, sem_args) == -1) {
        perror("semctl SETVAL failed");
        return 1;
    }

    // 主循环，等待客户端连接和事件
    struct epoll_event events[10];
    while (1) {
        int num_events = epoll_wait(epoll_fd, events, 10, -1);
        if (num_events == -1) {
            perror("Epoll wait failed");
            break;
        }

        for (int i = 0; i < num_events; i++) {
            if (events[i].data.fd == server_socket) {
                // 处理客户端连接请求
                handle_client_connection(server_socket);
            } else {
                // 处理客户端数据和发送命令
                receive_client_data(events[i].data.fd);
                // 这里可以根据具体逻辑决定是否发送命令给客户端
                // 例如，根据某些条件发送控制命令
                send_command_to_client(events[i].data.fd, "COMMAND");
            }
        }
    }

    // 释放共享内存
    if (munmap(shared_memory, sizeof(char) * 1024) == -1) {
        perror("munmap failed");
    }
    if (shmctl(shared_memory_fd, IPC_RMID, NULL) == -1) {
        perror("shmctl failed");
    }

    // 删除信号量
    if (semctl(sem_id, 0, IPC_RMID) == -1) {
        perror("semctl IPC_RMID failed");
    }

    // 关闭服务器套接字
    close(server_socket);

    return 0;
}

void handle_client_connection(int server_socket) {
    // 接受客户端连接
    struct sockaddr_in client_addr;
    socklen_t client_addr_len = sizeof(client_addr);
    int client_socket = accept(server_socket, (struct sockaddr *)&client_addr, &client_addr_len);
    if (client_socket == -1) {
        perror("Accept failed");
    } else {
        // 将客户端信息存储到数组中
        clients[client_count].client_socket = client_socket;
        clients[client_count].client_addr = client_addr;

        // 这里可以进行一些初始化操作，如发送欢迎消息等
        char welcome_message[] = "Welcome to the server!";
        if (send(client_socket, welcome_message, strlen(welcome_message), 0) == -1) {
            perror("Send welcome message failed");
        }

        client_count++;
    }
}

void receive_client_data(int client_socket) {
    // 接收客户端发送的数据
    char buffer[1024];
    ssize_t bytes_read = recv(client_socket, buffer, sizeof(buffer), 0);
    if (bytes_read == -1) {
        perror("Recv failed");
    } else if (bytes_read == 0) {
        // 客户端关闭连接
        printf("Client disconnected\n");
        close(client_socket);
    } else {
        // 将接收到的数据写入共享内存（使用信号量进行同步）
        sem_wait((struct sembuf *)&sem_id, 0, -1);
        strcpy((char *)shared_memory, buffer);
        sem_post((struct sembuf *)&sem_id, 0, 1);

        // 这里可以根据数据内容进行一些处理，如记录日志、触发其他操作等
        printf("Received data from client: %s\n", buffer);
    }
}

void send_command_to_client(int client_socket, const char *command) {
    // 向客户端发送命令
    if (send(client_socket, command, strlen(command), 0) == -1) {
        perror("Send command to client failed");
    }
}